///////////////////////////////////////////////////////////////////////////////
//
// Licensed under the MIT License
//
// Copyright (c) 2010 Chris Colinsky
// All Rights Reserved
//
// version	0.5
// http://code.google.com/p/sugarcookie/
// http://code.google.com/p/sugarcookie/wiki/License
//
////////////////////////////////////////////////////////////////////////////////

package sugarcookie.components.videoPlayer {
	import com.greensock.TweenMax;
	import com.greensock.easing.Linear;
	
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	import sugarcookie.display.SpriteBase;
	import sugarcookie.notifications.Notification;
	import sugarcookie.utils.IObservable;
	import sugarcookie.utils.IObserver;
	import sugarcookie.utils.Observable;
	
	public class BasicSeekBar extends SpriteBase implements IObservable {
		private var _track:Sprite;
		private var _load_progress:Sprite;
		private var _play_progress:Sprite;
		private var _playhead:MovieClip;
		private var _dragRect:Rectangle;
		
		private var _notifier:Observable;
		
		private var _startX:Number;
		private var _barWidth:Number;
		private var _isStreaming:Boolean = false;
		
		public function BasicSeekBar(props:Object=null) {
			super(props);
			assignGraphics();
			internal_init();
		}
		
		//Observable methods
		final public function addObserver(observer:IObserver,notificationType:String="all"):Boolean {
			return _notifier.addObserver(observer,notificationType);
		}
		
		final public function removeObserver(observer:IObserver,notificationType:String="all"):Boolean {
			return _notifier.removeObserver(observer,notificationType);
		}
		
		final public function clearObservers():void {
			_notifier.clearObservers();
		}
		
		final public function countObservers():Number {
			return _notifier.countObservers();
		}
		
		final public function get useLogging():Boolean { return _notifier.useLogging; }
		final public function set useLogging(value:Boolean):void { _notifier.useLogging = value; }
		
		final public function update(notification:Notification):void {
			switch (notification.type) {
			}
		}
		
		final public function set isStreaming(value:Boolean):void { _isStreaming = value }
		
		final public function updateLoadProgress(percent:Number,dur:Number=.75,complete:Boolean=false):void {
			if (!_load_progress) return;
			if (percent>1) percent = 1;
			TweenMax.killTweensOf(_load_progress,complete);
			TweenMax.to(_load_progress,dur,{width:_barWidth*percent});
		}
		
		final public function updatePlayProgress(percent:Number,dur:Number=1,complete:Boolean=false):void {
			dur = dur==-1?0:dur;
			if (percent>1) percent = 1;
			
			TweenMax.killTweensOf(_play_progress,complete);
			TweenMax.killTweensOf(_playhead,complete);
			
			var _progressWidth:Number = _barWidth*percent;
			TweenMax.to(_play_progress,dur,{width:_progressWidth<0?0:_progressWidth,ease:Linear.easeNone});
			var _playHeadX:Number = _startX+_barWidth*percent;
			TweenMax.to(_playhead,dur,{x:_playHeadX<0?0:_playHeadX,ease:Linear.easeNone});
		}
		
		final protected function set barWidth(value:Number):void {
			_barWidth = value;
		}
		
		final protected function set track(value:Sprite):void { 
			addChild(_track = value);
			_track.addEventListener(MouseEvent.CLICK,skipToClick);
		}
		final protected function get track():Sprite { return _track; }

		final protected function set load_progress(value:Sprite):void { 
			addChild(_load_progress = value); 
			_load_progress.mouseEnabled = false;
		}
		final protected function get load_progress():Sprite { return _load_progress; }

		final protected function set play_progress(value:Sprite):void { 
			addChild(_play_progress = value);
			_play_progress.mouseEnabled = false;
		}
		final protected function get play_progress():Sprite { return _play_progress; }
		
		//TODO, make playhead an assignable BasicButton
		final protected function set playhead(value:MovieClip):void { 
			addChild(_playhead = value);
			_startX = _playhead.x;
			_playhead.buttonMode = true;
			_playhead.mouseChildren = false;
			_playhead.addEventListener(MouseEvent.MOUSE_DOWN,mousedown);
		}
		final protected function get playhead():MovieClip { return _playhead; }
		
		protected function assignGraphics():void {
			// to be overridden by subclass
		}
		
		private function notifyObservers(type:String,data:Object=null):void {
			_notifier.setChanged();
			_notifier.notifyObservers(type,data);
		}
		
		private function skipToClick(evt:MouseEvent):void {
			var p:Number;
			if (_isStreaming) p = evt.localX/_track.width;
			else p = evt.localX<=_load_progress.width? evt.localX/_track.width : _load_progress.width/_track.width;
			
			updatePlayProgress(p,-1);
			notifyObservers(VideoController.SEEK,{percent:p});
		}
		
		private function mousedown(evt:MouseEvent):void {
			_playhead.removeEventListener(MouseEvent.MOUSE_DOWN,mousedown);
			_playhead.addEventListener(MouseEvent.MOUSE_UP,mouseup);
			stage.addEventListener(MouseEvent.MOUSE_UP,mouseup);
			stage.addEventListener(Event.MOUSE_LEAVE,mouseup);
			
			TweenMax.killTweensOf(_play_progress);
			TweenMax.killTweensOf(_playhead);
			
			notifyObservers(VideoController.SCRUB);
			_dragRect = new Rectangle(_startX,_playhead.y,_isStreaming?_track.width:_load_progress.width,0);
			_playhead.startDrag(false,_dragRect);
			addEventListener(Event.ENTER_FRAME,enterFrame);
		}
		
		private function mouseup(evt:MouseEvent):void {
			_playhead.removeEventListener(MouseEvent.MOUSE_UP,mouseup);
			stage.removeEventListener(MouseEvent.MOUSE_UP,mouseup);
			stage.removeEventListener(Event.MOUSE_LEAVE,mouseup);
			_playhead.addEventListener(MouseEvent.MOUSE_DOWN,mousedown);
			
			notifyObservers(VideoController.SEEK,{percent:(_playhead.x-_startX)/_track.width});
			_playhead.stopDrag();
			removeEventListener(Event.ENTER_FRAME,enterFrame);
		}
		
		private function enterFrame(evt:Event):void {
			var _width:Number = _barWidth*((_playhead.x-_startX)/_track.width);
			_dragRect.width = _isStreaming?_track.width:_load_progress.width;
			_playhead.stopDrag();
			_playhead.startDrag(false,_dragRect);
			_play_progress.width = _width<0?0:_width;
		}
		
		private function internal_init():void {
			_notifier = new Observable(this);
			_barWidth = _track.width;
			if (_load_progress) _load_progress.width = 0;
			_play_progress.width = 0;
		}
	}
}